package com.biblioteca.controlador;

import com.biblioteca.persistencia.Rol;
import com.biblioteca.persistencia.Usuario;
import com.biblioteca.servicio.UsuarioServicio;
import com.biblioteca.view.utils.MessageProvider;
import com.google.appengine.api.datastore.Key;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.binding.message.MessageBuilder;

@Controller("usuarioControlador")
@Scope("request")
public class usuarioController {
    
    UsuarioServicio usuarioServicio;
    Usuario usuariologeado;
    Usuario usuario;
    Usuario usuarioseleccionado;
    String user;
    private Collection<Usuario> usuarios;
    private Collection<Rol> listaroles;
    private AuthenticationManager authenticationManager;

    String pass1;
    String pass2;
    int intentos;
    
    @Autowired
    @Required
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }
    
    @Autowired
    @Required
    public void setUsuarioServicio(UsuarioServicio usuarioServicio) {
        this.usuarioServicio = usuarioServicio;
    }
    
    @PostConstruct
    private void iniciar() {
        usuariologeado = new Usuario();
        usuario = new Usuario();
    }
    
    public Usuario getUsuarioseleccionado() {
        System.out.println("usuarioSelecionado recoge a " + usuarioseleccionado.getUsername());
        return usuarioseleccionado;
    }
    
    public void setUsuarioseleccionado(Usuario usuarioseleccionado) {
        this.usuarioseleccionado = usuarioseleccionado;
    }
    
    public Usuario getUsuario() {
        return usuario;
    }
    
    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    public int getIntentos() {
        return intentos;
    }

    public void setIntentos(int intentos) {
        this.intentos = intentos;
    }

    
    
    public Usuario getUsuariologeado() {
        return usuariologeado;
    }
    
    public void setUsuariologeado(Usuario usuariologeado) {
        this.usuariologeado = usuariologeado;
    }

    public String getPass1() {
        return pass1;
    }

    public void setPass1(String pass1) {
        this.pass1 = pass1;
    }

    public String getPass2() {
        return pass2;
    }

    public void setPass2(String pass2) {
        this.pass2 = pass2;
    }

    

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    
    
    public Collection<Usuario> getUsuarios() {
        if (usuarioServicio.getAllusuarios().isEmpty()) {
            System.out.println("Lista Usuarios Vacia");
        } else {
            System.out.println("Numero de Usuarios  =" + usuarioServicio.getAllusuarios().size());
        }
        return usuarioServicio.getAllusuarios();
    }
    
    public void setUsuarios(Collection<Usuario> usuarios) {
        this.usuarios = usuarios;
    }
    
    public Collection<Rol> getListaroles() {
        return listaroles;
    }
    
    public void setListaroles(Collection<Rol> listaroles) {
        this.listaroles = listaroles;
    }
    
    public void crearUsuario() {
        Rol r2 = new Rol();
        r2.setNombre("ROLE_USER");
        usuario.setSiadmin(false);
        usuarioServicio.crearUsuario(usuario);
        usuarioServicio.addRol(usuario, r2);
    }
    
    public void borrarUsuarios(RequestContext context) {
        usuarioServicio.borrar(usuarioseleccionado.getUsername());        

        FacesContext ctx = FacesContext.getCurrentInstance();
        ctx.addMessage(null, new FacesMessage("Correcto", "Usuario eliminado de nuestra base de datos"));

    }
    
    public String login(RequestContext context) {
        System.out.println("Iniciando Login");
        int i;
    Usuario us = usuarioServicio.getUsuario(usuariologeado.getUsername());

    if(us.getIntentos() == 3){
        us.setBloqueado(true);
        usuarioServicio.update(us);
    }
    if(us.getPassword().equals(usuariologeado.getPassword())){
        if(usuarioServicio.isBloqueado(usuariologeado.getUsername())){
            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(null, new FacesMessage("Error", "estas bloqueado"));
        }else{
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(usuariologeado.getUsername(), usuariologeado.getPassword());
        authToken.setDetails(authentication.getDetails());
        Authentication newAuth = authenticationManager.authenticate(authToken);
        SecurityContextHolder.getContext().setAuthentication(newAuth);
        if(newAuth.isAuthenticated()) {
            context.getFlowScope().put("usuario", usuarioServicio.getCurrentUser());
        }
        FacesContext ctx = FacesContext.getCurrentInstance();
        ctx.addMessage(null, new FacesMessage("Correcto", "Logeado correctamente, vuelve al inicio"));
        us.setIntentos(0);
        usuarioServicio.update(us);
        }
        
     }else{
            i=us.getIntentos();
            us.setIntentos(i+1);
            usuarioServicio.update(us);
            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(null, new FacesMessage("Error", "passwd incorrecto, tienes 3 intentos y lo has intentado "+ us.getIntentos()));
    }
        return "redirect:/index";

        
    }
    
    public void logout() throws java.io.IOException {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpSession httpSession = (HttpSession) facesContext.getExternalContext().getSession(false);
        httpSession.invalidate();
    }
    
    public void nombrarAdmin() {
        List<Key> roles = this.usuarioseleccionado.getRoles();
        if (roles.size() < 2) {
            boolean esDel = roles.removeAll(roles);
            if (true) {
                this.usuarioseleccionado.setSiadmin(true);
                usuarioServicio.crearAdmin(this.usuarioseleccionado);
                usuarioServicio.update(this.usuarioseleccionado);
            }
        }

        FacesContext ctx = FacesContext.getCurrentInstance();
        ctx.addMessage(null, new FacesMessage("Correcto", "el usuario ahora es" + usuarioseleccionado.getRoles()));

    }
    
    public Usuario getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication.isAuthenticated()) {
            String username = authentication.getName();
            return usuarioServicio.getUsuario(username);
        } else {
            return null;
        }
    }
    
    public void ActualizarUsuario(Usuario actulizado) {
        usuarioServicio.update(actulizado);

        FacesContext ctx = FacesContext.getCurrentInstance();
        ctx.addMessage(null, new FacesMessage("Correcto", "Usuario actualizado correctamente"));

    }

    public void bloquear(){
        if(usuarioseleccionado.isBloqueado()){
            usuarioseleccionado.setBloqueado(false);
            usuarioseleccionado.setIntentos(0);
            usuarioServicio.update(usuarioseleccionado);

            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(null, new FacesMessage("Correcto", "El usuario ha sido desbloqueado"));
            
        }else{
        usuarioseleccionado.setBloqueado(true);
        usuarioServicio.update(usuarioseleccionado);

        FacesContext ctx = FacesContext.getCurrentInstance();
        ctx.addMessage(null, new FacesMessage("Correcto", "El usuario ha sido bloqueado"));
        }
    }

    public void actualizarContrasena(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        Usuario u = usuarioServicio.getUsuario(username);
        if(pass1.equals(u.getPassword())){
            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(null, new FacesMessage("Error", "password igual al antiguo, introdusca uno nevo"));
        }else{
        if(u.getPassword().equals(user) ){
            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(null, new FacesMessage("Correcto", "password correcto"));

            if(pass1.equals(pass2)){
                if(pass1.length() < 6){
                    ctx.addMessage(null, new FacesMessage("Error", "La contrasena es muy corta"));
                    
                }else{
                    u.setPassword(pass1);
                    usuarioServicio.update(u);
                    ctx.addMessage(null, new FacesMessage("Ok", "passwd combiado correctamente"));
                }
            }



        }else{
            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(null, new FacesMessage("Error", "password incorrecto, Introdusca los datos de nuevo"));
        }
        }
    }
    
    public void convertirUser() {
        System.out.println("1 Dando rol de administrador");
        List<Key> roles = this.usuarioseleccionado.getRoles();
        if (roles.size() < 2) {
            boolean esDel = roles.removeAll(roles);
            System.out.println("roles eliminados" + esDel);
            if (true) {
                this.usuarioseleccionado.setSiadmin(false);
                usuarioServicio.vUser(this.usuarioseleccionado);
                System.out.println("1 Actualizando usuario");
                usuarioServicio.update(this.usuarioseleccionado);
                System.out.println("1 Actualizado correctamente y sin errores de Compilacion");
            }
            
        } else {
            System.out.println("El usuario posee demasiados roles");            
        }
        
    }
}
